home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / UUPC11QS.ARJ / UUPOLL.C < prev    next >
C/C++ Source or Header  |  1991-10-18  |  21KB  |  617 lines

  1. /*
  2.       Program:    uupoll.c              22 September 1989
  3.       Author:     Andrew H. Derbyshire
  4.                   108 Decatur St
  5.                   Arlington, MA 02174
  6.       Internet:   help@kew.com
  7.       Function:   Performs autopoll functions for UUCICO
  8.       Language:   Borland C++ 2.0
  9.       Usage:      uupoll [-r 0] [-f hhmm] [-i hhmm|0400 ] [-d hhmm]
  10.                          [-a hhmm] [-x debug] [-s systems]
  11.  
  12.                   Where:
  13.  
  14.                   -r 0     specifies that UUCICO is to run into
  15.                            passive mode when waiting to poll out
  16.  
  17.                   -r 1     specifies that UUCICO will not run in passive
  18.                            mode while waiting to poll out, but polling
  19.                            out will occur.
  20.  
  21.                   -f hhmm  is the first time in the day that uuio
  22.                            is to poll out.  If omitted, polling
  23.                            begins after the interval specified with
  24.                            -i.
  25.  
  26.                   -i hhmm  the interval the UUCICO is to poll out
  27.                            at.  If omitted, a period of 4 hours
  28.                            will be used.
  29.  
  30.                   -d hhmm  Terminate polling after hhmm.  Default is
  31.                            not to terminate.
  32.  
  33.                   -a hhmm  Automatically poll actively using the system
  34.                            name "any" after any successfully inbound
  35.                            poll if hhmm have past since last poll.  hhmm
  36.                            may be 0000.
  37.  
  38.                   In addition, the following flags will be passed
  39.                   to UUCICO:
  40.  
  41.                   -s system      system name to poll.  By default,
  42.                                  UUCICO will be invoked with '-s all'
  43.                                  followed by '-s any'.
  44.  
  45.                   -x n           debug level.   The default level
  46.                                  is 1.
  47.  
  48.  */
  49.  
  50. #include <assert.h>
  51. #include <ctype.h>
  52. #include <dos.h>
  53. #include <limits.h>
  54. #include <process.h>
  55. #include <stdio.h>
  56. #include <stdlib.h>
  57. #include <string.h>
  58. #include <time.h>
  59. #include <conio.h>
  60. #include <direct.h>
  61.  
  62. #ifdef __TURBOC__
  63. #include <alloc.h>
  64. unsigned _stklen = 2048;            /* Reduce memory usage           */
  65. unsigned _heaplen = 2048;           /* Reduce memory usage           */
  66. #else
  67. #ifndef FAMILYAPI
  68. static int setcbrk(char state);
  69. #endif
  70. #endif
  71.  
  72. #include "getopt.h"
  73. #include "lib.h"
  74. #include "timestmp.h"
  75. #include "ssleep.h"
  76. #ifdef DEBUG
  77. #define printmsg(a,b,c) /* printmsg(a,b,c) */
  78. #include "arpadate.h"
  79. #include "arpadate.c"
  80. #endif
  81.  
  82. typedef int hhmm;
  83.  
  84. #define hhmm2sec(HHMM)    ((time_t)(((HHMM / 100) * 60L) + \
  85.                            (time_t)(HHMM % 100)) * 60L)
  86.  
  87. static int     active(char *Rmtname, int debuglevel);
  88. static void    busywork( time_t next);
  89. static int     execute( char *command );
  90. static time_t  nextpoll( hhmm first, hhmm interval );
  91. static boolean     notanumber( char *number);
  92. static int     passive( time_t next, int debuglevel );
  93. static void    usage( char *name );
  94. static hhmm    firstpoll(hhmm interval);
  95. static void    uuxqt( int debuglevel);
  96.  
  97. static time_t now;            /* Current time, updated at start of
  98.                                  program and by busywork() and
  99.                                  execute()                           */
  100.  
  101. /*--------------------------------------------------------------------*/
  102. /*    m a i n                                                         */
  103. /*                                                                    */
  104. /*    main program                                                    */
  105. /*--------------------------------------------------------------------*/
  106.  
  107.  main( int argc , char *argv[] )
  108.  {
  109.  
  110.    int option;
  111.    hhmm first = - 1;
  112.    hhmm interval = -1;
  113.    time_t duration = LONG_MAX;
  114.    int nopassive = 2;
  115.    boolean autoforward = TRUE;
  116.    boolean done = FALSE;
  117.    time_t autowait;
  118.    char *Rmtname = NULL;
  119.    int debuglevel = 1;
  120.    int returncode = 0;
  121.  
  122. #ifndef FAMILYAPI
  123.    boolean cbrk;
  124. #endif
  125.  
  126.    banner(argv);
  127.    tzset();
  128.    time( &now );
  129.  
  130.    while((option = getopt(argc, argv, "a:d:f:i:s:r:x:")) != EOF)
  131.    switch(option)
  132.    {
  133.  
  134. /*--------------------------------------------------------------------*/
  135. /*       Automatically poll "any" after an incoming phone call        */
  136. /*--------------------------------------------------------------------*/
  137.  
  138.       case 'a':
  139.          autoforward = TRUE;
  140.          if (notanumber(optarg))
  141.             usage( argv[0] );
  142.          autowait = hhmm2sec( atoi(optarg) );
  143.          break;
  144.  
  145. /*--------------------------------------------------------------------*/
  146. /*                         First time to poll                         */
  147. /*--------------------------------------------------------------------*/
  148.  
  149.       case 'f':
  150.          if (notanumber(optarg))
  151.             usage( argv[0] );
  152.          first = atoi(optarg);
  153.          if ( interval == -1 )
  154.             interval = 400;
  155.          break;
  156.  
  157. /*--------------------------------------------------------------------*/
  158. /*                          Interval to poll                          */
  159. /*--------------------------------------------------------------------*/
  160.  
  161.       case 'i':
  162.          if (notanumber(optarg))
  163.             usage( argv[0] );
  164.          interval = atoi(optarg);
  165.          nopassive = min(1,nopassive);
  166.          break;
  167.  
  168. /*--------------------------------------------------------------------*/
  169. /*                      Time (duration) to poll                       */
  170. /*--------------------------------------------------------------------*/
  171.  
  172.       case 'd':
  173.          if (notanumber(optarg))
  174.             usage( argv[0] );
  175.          duration  = atoi(optarg);
  176.          break;
  177.  
  178. /*--------------------------------------------------------------------*/
  179. /*                        System name to poll                         */
  180. /*--------------------------------------------------------------------*/
  181.  
  182.       case 's':
  183.          Rmtname = strdup(optarg);
  184.          break;
  185.  
  186. /*--------------------------------------------------------------------*/
  187. /*                            Debug level                             */
  188. /*--------------------------------------------------------------------*/
  189.  
  190.       case 'x':
  191.          if (notanumber(optarg))
  192.             usage( argv[0] );
  193.          debuglevel = atoi(optarg);
  194.          break;
  195.  
  196. /*--------------------------------------------------------------------*/
  197. /*                       Passive polling option                       */
  198. /*--------------------------------------------------------------------*/
  199.  
  200.       case 'r':
  201.          if (notanumber(optarg))
  202.             usage( argv[0] );
  203.          nopassive = atoi(optarg);
  204.          break;
  205.  
  206. /*--------------------------------------------------------------------*/
  207. /*                                Help                                */
  208. /*--------------------------------------------------------------------*/
  209.  
  210.       default:
  211.       case '?':
  212.          usage( argv[0] );
  213.    } /* switch */
  214.  
  215. /*--------------------------------------------------------------------*/
  216. /*             Terminate with error if too many arguments             */
  217. /*--------------------------------------------------------------------*/
  218.  
  219.    if (optind != argc)
  220.    {
  221.       puts("Extra parameters on command line.");
  222.       usage( argv[0] );
  223.    }
  224.  
  225. /*--------------------------------------------------------------------*/
  226. /* Terminate if neither active polling nor passive polling requested  */
  227. /*--------------------------------------------------------------------*/
  228.  
  229.    if ( nopassive == 2 && (first < 0))
  230.    {
  231.       puts("Must specify -r 0, -f hhmm, or -i hhmm");
  232.       usage( argv[0] );
  233.    }
  234.  
  235.    if ( (interval > 0) && (first < 0))
  236.       first = firstpoll(interval);
  237.  
  238. /*--------------------------------------------------------------------*/
  239. /*            If running under MS-DOS, enable Cntrl-Break.            */
  240. /*--------------------------------------------------------------------*/
  241.  
  242. #ifndef FAMILYAPI
  243. #ifdef __TURBOC__
  244.    cbrk = getcbrk();                /* Get original Cntrl-Break setting */
  245.  
  246.    if (!cbrk)
  247.       setcbrk(1);                   /* Turn it on to allow abort        */
  248. #else /*dmw*/
  249.    cbrk = setcbrk(1);      /* Turn it on to allow abort; get previous state */
  250.    printf("BREAK ON has been set\n");
  251. #endif
  252. #endif
  253.  
  254. /*--------------------------------------------------------------------*/
  255. /*    If a quitting internal was specified, convert it to an          */
  256. /*    absolute time                                                   */
  257. /*--------------------------------------------------------------------*/
  258.  
  259.    if (duration != LONG_MAX)
  260.    {
  261.       duration = hhmm2sec( duration ) + (now / 60L) * 60L;
  262.                                     /* Round to next lower minute    */
  263.       printf("Will terminate upon completion of first event \
  264. after %s", ctime(&duration));
  265.    } /* if */
  266.  
  267. /*--------------------------------------------------------------------*/
  268. /*                       Beginning of main loop                       */
  269. /*--------------------------------------------------------------------*/
  270.  
  271.    while ( !done && (duration > now))
  272.    {
  273.       time_t next = LONG_MAX;
  274.       time_t autonext = now + autowait;
  275.       time_t wait = 10;      /* Time to wait after first panic()    */
  276.  
  277.       if (first >= 0)
  278.          next = nextpoll(first,interval);
  279.       else
  280.          next = duration;
  281.  
  282.       while ((now < next) && ! done )
  283.       {
  284.          if (nopassive)
  285.             busywork(next);
  286.          else {
  287.             time_t spin;
  288.             returncode = passive(next,debuglevel);
  289.             if (returncode == 69 )  /* Error in UUCICO?              */
  290.             {                       /* Yes --> Allow time to fix it  */
  291.                spin = now + wait;   /* Figure next wait              */
  292.                wait *= 2 ;          /* Double wait for next time     */
  293.                busywork( spin > next ? next : spin );
  294.                                     /* But only wait till next poll  */
  295.             } /* if (returncode == 69 ) */
  296.             else {
  297.                wait = 10;
  298.                if ((returncode == 0) && autoforward && (now > autonext))
  299.                {
  300.                   returncode = active("any",debuglevel);
  301.                   autonext = now + autowait;
  302.                } /* if */
  303.             } /* else */
  304.  
  305.             if ( (now > duration) && (now < next))
  306.                done = TRUE;
  307.             else if ( returncode == 100 )
  308.                done = TRUE;
  309.  
  310.          } /* else */
  311.  
  312.       } /* while */
  313.  
  314.       if ( ! done && (first >= 0) )
  315.       {
  316.          returncode = active(Rmtname,debuglevel);
  317.          if ( returncode == 100 )
  318.             done = TRUE;
  319.       } /* if ( ! done && (first >= 0) ) */
  320.  
  321.    } /* while */
  322.  
  323. /*--------------------------------------------------------------------*/
  324. /*                          End of main loop                          */
  325. /*--------------------------------------------------------------------*/
  326.  
  327.    uuxqt( debuglevel );          /* One last call to UUXQT                 */
  328.  
  329. #ifndef FAMILYAPI
  330.    if (!cbrk)
  331.       setcbrk(0);                /* Restore original Cntrl-Break setting   */
  332. #endif
  333.  
  334.    return(returncode);
  335.  } /* main */
  336.  
  337.  
  338. /*--------------------------------------------------------------------*/
  339. /*    a c t i v e                                                     */
  340. /*                                                                    */
  341. /*    Perform an active (outgoing) poll of other hosts                */
  342. /*--------------------------------------------------------------------*/
  343.  
  344.  static active(char *Rmtname, int debuglevel)
  345.  {
  346.    int result;
  347.  
  348.    if (Rmtname == NULL)             /* Default?                         */
  349.    {                                /* Yes --> do -s all and -s any     */
  350.       if (active("all",debuglevel) < 100)
  351.          return active("any",debuglevel);
  352.       else
  353.          return 100;
  354.    }
  355.    else {
  356.       char buf[128];
  357.       sprintf(buf,"uucico -r 1 -s %s -x %d",Rmtname,debuglevel);
  358.       result = execute(buf);
  359.       if ( result == 0 )
  360.          uuxqt( debuglevel );
  361.  
  362.       return result;
  363.    }
  364.  } /* active */
  365.  
  366. /*--------------------------------------------------------------------*/
  367. /*    b u s y w o r k                                                 */
  368. /*                                                                    */
  369. /*    Waits for next time to poll without answering the telephone.    */
  370. /*    Maybe we should at least beep on the hour?  :-)                 */
  371. /*--------------------------------------------------------------------*/
  372.  
  373. static void busywork( time_t next)
  374. {
  375.    time_t naptime;
  376.    time_t hours, minutes, seconds;
  377.  
  378.    naptime = next - now;
  379.  
  380.    hours   = (naptime / 3600) % 24;    /* Get pretty time to display... */
  381.    minutes = (naptime / 60) % 60;
  382.    seconds = naptime % 60;
  383.  
  384.    printf("Going to sleep for %02ld:%02ld:%02ld, next poll is %s",
  385.              hours, minutes, seconds, ctime(&next) );
  386.    ssleep( naptime );
  387.  
  388.    time( & now );
  389. }
  390.  
  391.  
  392. /*--------------------------------------------------------------------*/
  393. /*    e x e c u t e                                                   */
  394. /*                                                                    */
  395. /*    Executes a command via a spawn() system call.  This avoids      */
  396. /*    the storage overhead of COMMAND.COM and returns the actual      */
  397. /*    return code from the command executed.                          */
  398. /*                                                                    */
  399. /*    Note that this does not allow quoted command arguments, which   */
  400. /*    not a problem for the intended argv[0]s of UUCICO.              */
  401. /*--------------------------------------------------------------------*/
  402.  
  403.  static int execute( char *command )
  404.  {
  405.    char *argv[20];
  406.    int argc = 0;
  407.    int result;
  408. #ifdef DEBUG
  409.    FILE *stream = NULL;
  410. #endif
  411.  
  412.    printf("Executing command: %s\n",command);
  413. #ifdef DEBUG                  /* ahd */
  414.    stream = fopen("UUPOLL.LOG","a");
  415.    if (stream == NULL)
  416.    {
  417.       perror("UUPOLL.LOG");
  418.       abort();
  419.    } /* if */
  420.    fprintf(stream, "%s: %s\n",arpadate(), command);
  421.    fclose(stream);
  422. #endif /* DEBUG */
  423.  
  424.    argv[argc] = strtok(command," \t");
  425.  
  426.    while ( argv[argc++] != NULL )
  427.       argv[argc] = strtok( NULL," \t");
  428.    result = spawnvp(P_WAIT , argv[0] , argv );
  429.    if ( result < 0 )
  430.    {
  431.       printf("\a\nCommand \"%s\" failed!\n\a", argv[0]);
  432.       abort();
  433.    }
  434.  
  435.    time( & now );
  436.    return result;
  437. }
  438.  
  439. /*--------------------------------------------------------------------*/
  440. /*    n e x t p o l l                                                 */
  441. /*                                                                    */
  442. /*    Returns next time to poll in seconds                            */
  443. /*                                                                    */
  444. /*    modified 14 October 1990 By Ed Keith.                           */
  445. /*    modified 4 November 1990 by Drew Derbyshire.                    */
  446. /*--------------------------------------------------------------------*/
  447.  
  448. static time_t nextpoll( hhmm first, hhmm interval )
  449. {
  450.    time_t sfirst;
  451.    time_t sinterval = hhmm2sec( interval );
  452.    time_t today;
  453.    time_t tomorrow;
  454.    struct tm  *time_record;   /* Ed K. 10/14/1990 */
  455.  
  456.    time_record = localtime(&now); /* Ed K. 10/14/1990 */
  457.    time_record->tm_sec = 0;   /* Ed K. 10/14/1990 */
  458.    time_record->tm_min = 0;   /* Ed K. 10/14/1990 */
  459.    time_record->tm_hour= 0;   /* Ed K. 10/14/1990 */
  460.    today = mktime(time_record);
  461.    tomorrow = today + 86400;
  462.    sfirst = today + hhmm2sec(first);
  463.  
  464.    while (sfirst < now)
  465.       sfirst += sinterval;
  466.  
  467.    if (sfirst > tomorrow)
  468.       sfirst = tomorrow + hhmm2sec(first);
  469.  
  470.    return sfirst;
  471. } /* nextpoll */
  472.  
  473.  
  474. /*--------------------------------------------------------------------*/
  475. /*    f i r s t p o l l                                               */
  476. /*                                                                    */
  477. /*    Determine first time to poll if not specified                   */
  478. /*--------------------------------------------------------------------*/
  479.  
  480. static hhmm firstpoll(hhmm interval)
  481. {
  482.    struct tm  *time_record;
  483.    time_t sfirst;
  484.    hhmm first;
  485.  
  486.    time_record = localtime(&now);
  487.    sfirst = ((time_t) time_record->tm_hour * 3600L +
  488.              (time_t) time_record->tm_min * 60L);
  489.    sfirst  = sfirst % hhmm2sec(interval);
  490.    first = (hhmm) ((sfirst / 3600L) * 100L + (sfirst % 3600L) / 60L);
  491.  
  492.    printf("First polling time computed to be %-2.2d:%-2.2d\n",
  493.          first / 100, first % 100);
  494.    return first;
  495. } /* firstpoll */
  496.  
  497. /*--------------------------------------------------------------------*/
  498. /*    n o t a n u m b e r                                             */
  499. /*                                                                    */
  500. /*    Examines string, returns true if non-numeric                    */
  501. /*--------------------------------------------------------------------*/
  502.  
  503.  static boolean notanumber( char *start)
  504.  {
  505.    char *number = start;
  506.    while (*number != '\0')
  507.    {
  508.       if (!isdigit(*number))
  509.       {
  510.          printf("Parameter must be numeric, was %s\n",start);
  511.          return TRUE;
  512.       }
  513.       number++;
  514.    }
  515.    return FALSE;
  516.  } /* notanumber */
  517.  
  518.  
  519. /*--------------------------------------------------------------------*/
  520. /*    p a s s i v e                                                   */
  521. /*                                                                    */
  522. /*    Invoke UUCICO in passive mode until next active poll (if any).  */
  523. /*--------------------------------------------------------------------*/
  524.  
  525.  static int passive( time_t next, int debuglevel )
  526.  {
  527.    char buf[128];             /* Buffer for execute() commands          */
  528.    int result;
  529.    sprintf(buf,"uucico -r 0 -x %d",debuglevel);
  530.  
  531.    if (next > 0)              /* Should we poll out?                    */
  532.    {                          /* Yes --> Compute time to poll           */
  533.       char xnow[5];            /* Current time as a string              */
  534.       char then[5];           /* Next time to poll as a string          */
  535.       struct tm *tm_now;      /* Format time in integer values          */
  536.  
  537.       tm_now = localtime(&now);   /* Get time broken down             */
  538.       sprintf(xnow,"%02d%02d", tm_now->tm_hour, tm_now->tm_min);
  539.  
  540. /*--------------------------------------------------------------------*/
  541. /*    Format the time to stop polling.  Note that to have the         */
  542. /*    system actively poll at time x, we compute the window to        */
  543. /*    passively poll to end at x-1, since the passive window will     */
  544. /*    remain open until x-1 + 59 seconds.                             */
  545. /*--------------------------------------------------------------------*/
  546.  
  547.       if ( (next - now) > 120)   /* Poll at least two minutes?       */
  548.          next--;                 /* Yes --> End at start of the min  */
  549.  
  550.       tm_now = localtime(&next); /* Get time broken down            */
  551.       sprintf(then,"%02d%02d", tm_now->tm_hour, tm_now->tm_min);
  552.       strcat(buf," -u Any");
  553.       strcat(buf,xnow);
  554.       strcat(buf,"-");
  555.       strcat(buf,then);
  556.    }
  557.  
  558.    result = execute(buf);
  559.    if ( result == 0 )
  560.       uuxqt( debuglevel );
  561.    return result;
  562.  } /* passive */
  563.  
  564. /*--------------------------------------------------------------------*/
  565. /*    u u x q t                                                       */
  566. /*                                                                    */
  567. /*    Execute the UUXQT program to run files received by UUCICO       */
  568. /*--------------------------------------------------------------------*/
  569.  
  570.  static void uuxqt( int debuglevel)
  571.  {
  572.    int result;
  573.    char buf[128];             /* Buffer for execute() commands          */
  574.  
  575.    sprintf(buf,"uuxqt -x %d", debuglevel);
  576.    result = execute(buf);
  577.    assert( result == 0 );
  578.  } /* uuxqt */
  579.  
  580.  
  581. /*--------------------------------------------------------------------*/
  582. /*    u s a g e                                                       */
  583. /*                                                                    */
  584. /*    Report correct usage of the program and then exit.              */
  585. /*--------------------------------------------------------------------*/
  586.  
  587.  static void usage( char *name )
  588.  {
  589.    printf("Usage:\t%s\
  590. \t[-a hhmm] [-d hhmm] [-f hhmm] [-i hhmm] \n\
  591. \t\t[-r 0 | 1] [-s system] [-x n]\n",name);
  592.    exit(4);
  593.  }
  594.  
  595. #ifndef FAMILYAPI
  596. #ifndef __TURBOC__
  597. /*
  598.       s e t c b r k
  599.  
  600.       Enable Cntrl-Break
  601.  
  602.       Written by Dave Watts
  603.  */
  604.  
  605. static int setcbrk(char state)
  606. {
  607.    union REGS inregs, outregs;
  608.  
  609.    inregs.x.ax = 0x3302;
  610.    inregs.h.dl = state;
  611.    intdos(&inregs, &outregs);
  612.  
  613.    return outregs.h.dl;
  614. }
  615. #endif
  616. #endif
  617.